from flask import Flask, render_template, jsonify, request
from flask_cors import CORS
from datetime import datetime, timedelta
import time
import json
from pulsar import Client, MessageId, AuthenticationToken
from env import TOKEN, SENSOR_TOPIC, CONTROL_TOPIC, DEEPSEEK_API_KEY
import threading
import queue
import signal
import sys
from chat_module import ChatModule
from deepseek_chat import DeepSeekChat
import os
import logging

# 配置 Werkzeug 日志
werkzeug_log = logging.getLogger('werkzeug')
werkzeug_log.setLevel(logging.INFO)

# 创建一个过滤器来只允许启动信息
class StartupFilter(logging.Filter):
    def filter(self, record):
        return "Running on" in record.getMessage() or "* Running on" in record.getMessage()

# 添加过滤器
werkzeug_log.addFilter(StartupFilter())

app = Flask(__name__)
CORS(app)

# 全局变量
service_url = "pulsar+ssl://pulsar.cloud.unitestream.com:6651"

# 初始化 Pulsar 客户端，连接到指定服务，配置认证信息
client = Client(service_url, authentication=AuthenticationToken(TOKEN))
# 创建传感器数据生产者，用于向 SENSOR_TOPIC 发送数据
sensor_producer = client.create_producer(SENSOR_TOPIC)
# 创建传感器数据消费者，用于从 SENSOR_TOPIC 订阅和接收数据
sensor_consumer = client.subscribe(SENSOR_TOPIC, "sensor-data-subscription-1", properties={
    "consumer-name": "test-consumer-name",  # 消费者名称
    "consumer-id": "test-consumer-id"      # 消费者唯一标识
})
# 创建设备控制消费者，用于从 CONTROL_TOPIC 订阅和接收控制指令
control_consumer = client.subscribe(CONTROL_TOPIC, "control-data-subscription", properties={
    "consumer-name": "control-consumer-name",  # 消费者名称
    "consumer-id": "control-consumer-id"      # 消费者唯一标识
})
data_thread = None  # 传感器数据处理线程
control_thread = None  # 设备控制数据处理线程
running = True  # 全局运行标志
initialized = False  # 初始化标志

# 初始化聊天模块
chat_module = ChatModule()

# 初始化 DeepSeek 聊天模块，传入 API Key
deepseek_chat = DeepSeekChat(api_key=DEEPSEEK_API_KEY)  # 直接使用 API Key

# 数据队列，用于线程间传递数据
data_queue = queue.Queue()

# 当前传感器数据，保存最新的温度、湿度和水位
current_data = {
    'temperature': 25,
    'humidity': 50,
    'water_level': 30
}

# 当前设备状态，保存空调、除湿机和阀门的运行状态及参数
current_device_states = {
    'ac': {
        'running': False,
        'temperature': 24,
        'mode': '制冷'
    },
    'dehumidifier': {
        'running': False,
        'target': 50,
        'mode': '自动'
    },
    'valve': {
        'running': False,
        'opening': 0,
        'flow': 0
    }
}

# 历史数据，保存时间序列的温度、湿度和水位
history_data = {
    'timestamps': [],
    'temperature': [],
    'humidity': [],
    'water_level': []
}

def load_message_data(msg):
    data = json.loads(msg.data())
    timestamp = datetime.fromisoformat(data['timestamp'])

    # 更新当前数据
    current_data.update(data['values'])

    # 更新历史数据
    history_data['timestamps'].append(timestamp)
    history_data['temperature'].append(data['values']['temperature'])
    history_data['humidity'].append(data['values']['humidity'])
    history_data['water_level'].append(data['values']['water_level'])

def process_sensor_data():
    """
    传感器数据处理线程函数。
    持续从 Pulsar 的 SENSOR_TOPIC 主题接收传感器数据消息，
    解析后更新 current_data 和 history_data。
    """
    # 从 Pulsar 接收消息
    # 可使用load_message_data(msg) 加载数据以供前端展示。
    ################## LAB1 ###################################

    ###########################################################

def update_control_data(msg):
    data = json.loads(msg.data())
    # 更新当前设备状态
    global current_device_states
    current_device_states = data['device_states']

def process_control_data():
    """
    设备控制数据处理线程函数。
    持续从 CONTROL_TOPIC 主题接收设备控制消息，
    并根据消息内容更新 current_device_states。
    """

    ################### LAB2 #################################

    ##########################################################

def cleanup():
    """
    清理资源函数。
    关闭所有消费者、生产者和客户端，确保线程安全退出。
    """
    global running, data_thread, control_thread, sensor_consumer, control_consumer, sensor_producer, client, initialized
    print("正在清理资源...")
    running = False
    initialized = False
    
    # 快速关闭所有资源，防止资源泄漏
    if sensor_consumer:
        try:
            sensor_consumer.close()
        except:
            pass
    
    if control_consumer:
        try:
            control_consumer.close()
        except:
            pass
    
    if sensor_producer:
        try:
            sensor_producer.close()
        except:
            pass
    
    if client:
        try:
            client.close()
        except:
            pass
    
    # 等待线程结束，但最多等待1秒，防止阻塞
    if data_thread and data_thread.is_alive():
        data_thread.join(timeout=1)
    
    if control_thread and control_thread.is_alive():
        control_thread.join(timeout=1)
    
    print("资源清理完成")

def signal_handler(signum, frame):
    """
    信号处理函数。
    捕获退出信号（如 Ctrl+C 或 kill），调用 cleanup 进行资源清理。
    """
    print("\n收到退出信号，正在清理资源...")
    cleanup()
    sys.exit(0)

# 注册信号处理器，捕获 SIGINT（Ctrl+C）和 SIGTERM（kill）信号
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)


# 启动数据处理线程，负责处理传感器数据
data_thread = threading.Thread(target=process_sensor_data, daemon=True)
data_thread.start()

# 启动控制数据处理线程，负责处理设备控制数据
control_thread = threading.Thread(target=process_control_data, daemon=True)
control_thread.start()

@app.route('/')
def index():
    """
    首页路由，渲染前端页面。
    """
    return render_template('index.html')

@app.route('/api/sensor-data', methods=['GET'])
def get_sensor_data():
    """
    获取当前传感器数据的接口。
    """
    return jsonify(current_data)

@app.route('/api/history-data', methods=['GET'])
def get_history_data():
    """
    获取历史传感器数据的接口。
    """
    return jsonify({
        'timestamps': [t.isoformat() for t in history_data['timestamps']],
        'temperature': history_data['temperature'],
        'humidity': history_data['humidity'],
        'water_level': history_data['water_level']
    })

@app.route('/api/update-sensor', methods=['POST'])
def update_sensor():
    """
    更新传感器数据的接口。
    接收前端传来的传感器类型和数值，更新 current_data 并发送消息到 Pulsar。
    """
    data = request.json
    sensor_type = data.get('type')
    value = data.get('value')
    
    if sensor_type in current_data:
        # 更新当前数据
        current_data[sensor_type] = value
        
        # 创建消息，包含所有传感器数据
        message = {
            'timestamp': datetime.now().isoformat(),
            'values': {
                'temperature': current_data['temperature'],
                'humidity': current_data['humidity'],
                'water_level': current_data['water_level']
            }
        }

        ######################## LAB1 STUB ######################

        #########################################################
        return jsonify({'status': 'success', 'message': f'{sensor_type} updated successfully'})
    return jsonify({'status': 'error', 'message': 'Invalid sensor type'}), 400

@app.route('/api/device-status', methods=['GET'])
def get_device_status():
    """
    获取所有设备状态的接口。
    """
    return jsonify(current_device_states)

@app.route('/api/chat', methods=['POST'])
def chat():
    """
    聊天接口。
    接收用户问题，结合当前传感器数据和设备状态，调用 deepseek_chat 生成回复。
    """
    data = request.json
    user_query = data.get('query')
    
    if not user_query:
        return jsonify({'status': 'error', 'message': 'No query provided'}),

    
    try:
        # 获取当前传感器数据和设备状态
        response = deepseek_chat.generate_response(
            user_query=user_query,
            sensor_data=current_data,
            device_states=current_device_states
        )
        
        return jsonify({
            'status': 'success',
            'response': response
        })
        
    except Exception as e:
        return jsonify({
            'status': 'error',
            'message': str(e)
        }), 500

if __name__ == '__main__':
    # 禁用 Flask 的调试模式，避免重复初始化
    app.run(debug=False, port=5001)
